"""
NumPy 是python数值计算最重要的基础包,大多数提供科学计算的包都是用Numpy的数组作为构建基础
ndarray 一个具有矢量运算和复杂广播能力的快速且节省空间的多维数组
用于对整组数据进行快速运算的标准数学函数（无需编写循环）。
用于读写磁盘数据的工具以及用于操作内存映射文件的工具。
线性代数、随机数生成以及傅里叶变换功能。
用于集成由C、C++、Fortran等语言编写的代码的A C API。
用于数据整理和清理、子集构造和过滤、转换等快速的矢量化数组运算。
常用的数组算法，如排序、唯一化、集合运算等。
高效的描述统计和数据聚合/摘要运算。
用于异构数据集的合并/连接运算的数据对齐和关系型数据运算。
将条件逻辑表述为数组表达式（而不是带有if-elif-else分支的循环）。
数据的分组运算（聚合、转换、函数应用等）。。

NumPy之于数值计算特别重要的原因之一，是因为它可以高效处理大数组的数据。这是因为：

NumPy是在一个连续的内存块中存储数据，独立于其他Python内置对象。NumPy的C语言编写的算法库可以操作内存，而不必进行类型检查或其它前期工作。比起Python的内置序列，NumPy数组使用的内存更少。
NumPy可以在整个数组上执行复杂的计算，而不需要Python的for循环。

考察一个包含一百万整数的数组，和一个等价的Python列表：

In [7]: import numpy as np
In [8]: my_arr = np.arange(1000000)
In [9]: my_list = list(range(1000000))

In [10]: %time for _ in range(10): my_arr2 = my_arr * 2
CPU times: user 20 ms, sys: 50 ms, total: 70 ms
Wall time: 72.4 ms
In [11]: %time for _ in range(10): my_list2 = [x * 2 for x in my_list]
CPU times: user 760 ms, sys: 290 ms, total: 1.05 s
Wall time: 1.05 s

基于NumPy的算法要比纯Python快10到100倍（甚至更快），并且使用的内存更少。

NumPy最重要的一个特点就是其N维数组对象（即ndarray），该对象是一个快速而灵活的大数据集容器。你可以利用这种数组对整块数据执行一些数学运算，其语法跟标量元素之间的运算一样。
标准的NumPy惯用法import numpy as np。你当然也可以在代码中使用from numpy import *，但不建议这么做。numpy的命名空间很大，包含许多函数，其中一些的名字与Python的内置函数重名（比如min和max）。

先引入NumPy，然后生成一个包含随机数据的小数组：

ndarray是一个通用的同构数据多维容器 其中的所有元素必须是相同类型的.每个数组都有一个shape(一个表示各维度大小的元组)
和一个dtype 一个用于说明数组数据类型的对象
数组 NumPy数组 ndarray 时 基本上都指的是同一个样东西 即 ndarray对象

np.zeros
创建一个全为0的数组。
在创建数组时，NumPy 会确保每个元素都被显式地初始化为 0。
因为需要初始化所有元素，所以相对更耗时一些。
使用场景：当你明确需要一个初始值为 0 的数组时使用。
np.empty
创建一个“空”数组，但这里的“空”并不是指数组没有值，而是数组中的值是未定义的（可能是垃圾值）。
不会对数组中的元素进行初始化，因此速度更快。
使用场景：当你不需要初始值，或者会在后续代码中覆盖所有元素时使用。

总结
如果你需要一个初始值为 0 的数组，用 np.zeros。
如果你只需要一块内存空间，并且会自己填充数据，用 np.empty 更高效。
在 NumPy 中，ndim 和 shape 都是用于描述数组维度的属性，但它们有以下区别：
ndim
表示数组的维度数量（即数组的轴数）。
返回一个整数值。
例如：
一维数组 [1, 2, 3] 的 ndim 是 1。
二维数组 [[1, 2], [3, 4]] 的 ndim 是 2。
shape
表示数组的形状，返回一个元组，元组中的每个值表示对应维度的大小。
元组的长度等于 ndim。
例如：
一维数组 [1, 2, 3] 的 shape 是 (3,)。
二维数组 [[1, 2], [3, 4]] 的 shape 是 (2, 2)。

array
将输入数据（列表、元组、数组或其它序列类型）转换为ndarray。要么
推断出dtype,要么特别指定dtype。默认直接复制输入数据

asarray
将输入转换为ndarray,如果输入本身就是一个ndarray就不进行复制

arange
类似于内置的range,但返回的是一个ndarray而不是列表

ones,ones like
根据指定的形状和dtype创建一个全1数组。one like以另一个数组为参
数，并根据其形状和dtype创建一个全1数组

zeros,zeros like
类似于ones和ones like,只不过产生的是全0数组而已

empty,empty_like
创建新数组，只分配内存空间但不填充任何值

full,full like
用fill value中的所有值，根据指定的形状和dtype创建一个数组。full_like
使用另一个数组，用相同的形状和dtype创建

eye,identity
创建一个正方的N×N单位矩阵（对角线为1，其余为0）

dtype是NumPy灵活交互其它系统的源泉之一。多数情况下，它们直接映射到相应的机器表示，这使得“读写磁盘上的二进制数据流”以及“集成低级语言代码（如C、Fortran）”等工作变得更加简单。数值型dtype的命名方式相同：一个类型名（如float或int），后面跟一个用于表示各元素位长的数字。标准的双精度浮点值（即Python中的float对象）需要占用8字节（即64位）。因此，该类型在NumPy中就记作float64。表4-2列出了NumPy所支持的全部数据类型。

二维数组的索引方式 轴0作为行 轴1作为列

    0        1      2
0   0,0     0,1     0,2
1   1,0     1,1     1,2
2   2,0     2,1     2,2


import numpy as np
from unicodedata import numeric

# 生成一个2维3列的随机数组
data = np.random.randn(2,3)

# 进行数学运算
# data*10  所有的元素都乘以10
# data+data  每个元素都与自身相加
# data.shape (2,3)
# data.dtype (float64)

# 创建 ndarray 创建数组最简单的方法是使用array函数 它接收一切序列型的对象 包括其他数组 然后产生一个新的含有传入数据的NumPy数组
# 列表的转换
data1 = [4,3.5,46,89]
arr1 = np.array(data1)
# 嵌套序列 由一组等长列表组成的列表 将会被转换为一个多维数组
data2 = [[1,2,3,4],[5,6,7,8]]
arr2 = np.array(data2)
# data2是列表的列表 NumPy数组arr2的两个维度的shape是从data2引入 属性ndim和shape验证
# arr2.ndim
# arr2.shape
# arr1.dtype  数据类型保存在一个特殊的dtype对象中 获取数据类型
# 除np.array之外，还有一些函数也可以新建数组。比如，zeros和ones分别可以创建指定长度或形状的全0或全1数组。empty可以创建一个没有任何具体值的数组。要用这些方法创建多维数组，只需传入一个表示形状的元组即可：
np.zeros(10)  #生成一个长度或形状的全0或全1数组
np.zeros((3,6))  #生成一个3维6列的数组
np.empty((2,3,2)) #生成一个
# arange 是python内置函数range的数组版
np.arange(15)

# ndarray 的数据类型 dtype数据类型是一个特殊的对象
arr12 = np.array([1,2,3],dtype=np.float64)
arr13 = np.array([1,2,3],dtype=np.int32)
arr12.dtype  # 获取数据类型

arr14 = np.array([1,2,3,4,5])
arr14.dtype # 获取数据类型 int64

float_arr = arr14.astype(np.float64)  # 将数组转换为float64
float_arr.dtype # 获取数据类型 float64

# 整数被转换成了浮点数 将浮点数转换为整数
arr15 = np.array([3.7, -1.2, -2.6, 0.5, 12.9, 10.1])
arr15.astype(np.int32) # 将浮点数转换为整数

numeric_strings = np.array(['1.25','-9.6','42'],dtype=np.string_)
numeric_strings.astype(float)

# 数组 数组很重要，因为它使你不用编写循环即可对数据执行批量运算。NumPy用户称其为矢量化（vectorization）。大小相等的数组之间的任何算术运算都会将运算应用到元素级
arr16 = np.array([[1.,2.,3.],[4.,5.,6.]])
# arr16 * arr16 # 矩阵乘法 大小相等的数组之间的任何算术运算都会将运算应用到元素级
# 数组与标量的算术运算会标量值传播到各个元素上
# 1/arr16  arr16 ** 0.5
# 大小相同的数组之间的比较会生成布尔值数组
# arr16 > arr16  生成一个布尔数组 array([[False,  True, False],[ True, False,  True]], dtype=bool)
# 不同大小的数组之间的运算叫做广播

# 基本的索引和切片 NumPy 数组的索引是一个内容丰富的主题,选取数据子集或单个元素有很多
arr17 = np.arange(10)
arr17[5] # 获取第5个元素
arr17[5:8] # 获取第5到第8个元素
arr17[5:8] = 12 # 修改第5到第8个元素 全部改为12
# 当将一个标量值赋值给一个切片时 如(arr[5:8]=12) 该值会被自动传播到所有元素上 也就是广播
# 跟列表最重要的区别在于数组切片是原始数组的视图 这意味着数据不会被复制 视图上的任何修改都会反映到原始数组上
arr_slice = arr17[5:8]  #创建一个arr的切片
arr_slice[1] = 12345 # 修改切片中的第2个元素 变动会体现在原始数组上
# 切片[:] 会给数组中的所有值赋值
arr_slice[:] = 64 #array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])

# 由于NumPy的设计目的是处理大数据 如果你想要得到的是ndarray切片的一份副本而非视图，就需要明确地进行复制操作，例如arr[5:8].copy()。
# 一个二维数组中 各索引位置上的元素不再是标量而是一组数组
arr18 = np.array([[1,2,3],[4,5,6],[7,8,9]])
arr18[2] # 获取第3行
arr18[0][2] # 获取第1行第3列 3
arr18[0,2] # 获取第1行第3列 3 可以传入一个以逗号隔开的索引列表来选取单个元素

arr3d = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]])
old_values = arr3d[0].copy() # 复标量值和数组都可以被赋值给 arr3d[0]
arr3d[0] = 42

# 切片索引
arr = np.array([ 0,  1,  2,  3,  4, 64, 64, 64,  8,  9])
arr[1:6] # 获取第1到第6个元素

arr2d = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
arr2d[:2] # 获取前2行
# 二维数组是沿着第0轴即第一个轴切片的,切片是沿着一个轴向选取元素的,表达式 arr2d[:2] 获取arr2d的前两行
arr2d[:2, 1:] # 获取前2行第2列到第3列的元素
arr2d[:2, 2] # 获取前2行第3列的元素
arr2d[1, :2] # 获取第2行第1列到第2列的元素
arr2d[:,:1] # 获取第1列的元素  冒号表示选取整个轴 冒号后面没有数字表示选取整个轴

arr = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

# 用于存储数据的数组以及一个存储姓名的数组含有重复项 将使用numpy.random中的randn函数生成一些正态分布的随机数
name = np.array(['Bob', 'Joe', 'Will', 'Bob', 'Will', 'Joe', 'Joe'])
data = np.random.randn(7, 4)
names = 'Bob'

arr[:2, 1:]  # 获取第2到3行的第2列第3列的的元素
arr[2] # 获取第3行的元素
arr[2,:] # 获取第3行的元素
arr[2:,:] # 获取第3行到第3行的元素
arr[:,:2] # 获取第1到第3行的第1到第2列的元素
arr[1,:2] # 获取第2行的第1到第2列的元素
arr[1:2,:2] # 获取第2行的第1到第2列的元素
arr[:2,1:] = 0 #对切片表达式的赋值操作也会被扩散到整个选区

# 花式索引 指的是利用整数数组进行索引
arr = np.empty((8, 4))
for i in range(8):
    arr[i] = i

# 选取以特定顺序选取行子集,只需传入一个用于指定顺序的整数列表或 ndarray 即可
arr[[4,3,0,6]]
arr[[-3,-5,-7]] # 使用负数索引将会从末尾开始选取行

# np.arange(32)是NumPy 中的一个函数 生成一个等差数列的数组
# 参数 32表示生成从0到31的整数序列  生成一个一维数组
# .reshape((8,4)) 用于改变数组的形状即维度 但不会改变数组中的数据
# 参数(8,4) 表示 将数组重新组织8行4列的二维数组
# 前提条件式原数组的总元素数量必须等于新形状的总元素数量
# 原数组有32个元素,新形状(8,4) 也就 8*4=32个元素 因此可以成功 reshape

   np.arange(32).reshape((8, 4))
   # 输出:
   # array([[ 0,  1,  2,  3],
   #        [ 4,  5,  6,  7],
   #        [ 8,  9, 10, 11],
   #        [12, 13, 14, 15],
   #        [16, 17, 18, 19],
   #        [20, 21, 22, 23],
   #        [24, 25, 26, 27],
   #        [28, 29, 30, 31]])

转置是重塑的一种特殊形式，它返回的是源数据的视图（不会进行任何复制操作）
数组不仅有transpose方法还有特殊的T属性

# np.arange 是 NumPy 中的一个函数，用于生成一个等差数列的数组。
# 参数 15 表示生成从 0 到 14 的整数序列（共 15 个元素）
# 参数 (3, 5) 表示将数组重新组织为 3 行 5 列的二维数组。
# arr.T 转置是重塑的一种特殊形式，它会交换数组的行和列
# 对于二维数组 转置操作将会将第i行变为第i列 ,第j列变为第j行
# arr.T是数组 arr的转置属性 返回的是源数据的视图，不会进行任何复制操作。
# 如果原数组形状为 (3, 5)，那么 arr.T 的形状为 (5, 3)。
arr = np.arange(15).reshape((3,5))
arr_transpose = arr.T

# array([[ 0,  1,  2,  3,  4],
#        [ 5,  6,  7,  8,  9],
#        [10, 11, 12, 13, 14]])

转为

# array([[ 0,  5, 10],
#        [ 1,  6, 11],
#        [ 2,  7, 12],
#        [ 3,  8, 13],
#        [ 4,  9, 14]])


# np.random.randn(6, 3)
# np.random.randn 是 NumPy 中的一个函数，用于生成符合标准正态分布（均值为0，标准差为1）的随机数。
# 参数 (6, 3) 表示生成一个形状为 (6, 3) 的二维数组，即 6 行 3 列的矩阵。
# 每个元素都是从标准正态分布中随机抽取的浮点数。
# 矩阵转置：arr.T
# arr.T 是矩阵 arr 的转置操作。
# 转置会交换矩阵的行和列。如果原矩阵形状为 (6, 3)，那么转置后的矩阵形状为 (3, 6)
# 矩阵内积：np.dot(arr.T, arr)
# np.dot 是 NumPy 中用于计算两个数组的点积（内积）的函数。
# 对于矩阵来说，np.dot(A, B) 的结果是矩阵 A 和矩阵 B 的矩阵乘法。
# 条件：矩阵 A 的列数必须等于矩阵 B 的行数。
# 在本例中：
# arr.T 的形状为 (3, 6)。
# arr 的形状为 (6, 3)。
# 根据矩阵乘法规则，(3, 6) 和 (6, 3) 的乘积结果是一个形状为 (3, 3) 的矩阵。
# 计算过程： 假设 arr 的转置为 arr_T，那么 np.dot(arr.T, arr) 的每个元素计算方式如下：
# 结果矩阵的第 (i, j) 个元素是 arr_T 的第 i 行与 arr 的第 j 列的点积。
# 公式： [ C[i][j] = \sum_{k=1}^{n} A[i][k] \cdot B[k][j] ]
arr = np.random.randn(6,3)
np.dot(arr.T, arr)

 arr = np.arange(16).reshape((2, 2, 4))
(1) np.arange(16)
np.arange(16) 是 NumPy 中的一个函数，用于生成一个从 0 到 15 的等差数列数组（共 16 个元素）。
结果是一个一维数组：[0, 1, 2, ..., 15]。

(2) .reshape((2, 2, 4))
.reshape 是 NumPy 数组的一个方法，用于改变数组的形状（即维度），但不会改变数组中的数据。
参数 (2, 2, 4) 表示将数组重新组织为形状为 (2, 2, 4) 的三维数组。
前提条件是原数组的总元素数量必须等于新形状的总元素数量。这里原数组有 16 个元素，新形状 (2, 2, 4) 也有 2 × 2 × 4 = 16 个元素，因此可以成功 reshape。

array([[[ 0,  1,  2,  3],
        [ 4,  5,  6,  7]],

       [[ 8,  9, 10, 11],
        [12, 13, 14, 15]]])

这是一个三维数组，形状为 (2, 2, 4)，表示有两个二维平面（每个平面形状为 (2, 4)）。
三维数组把(2,2,4) 变型为 (2,(2,4)) 即2个(2,4)矩阵 就成了三维数组
可以理解为 三维数组 是有2个 (2,4)的矩阵平面构成
第0个矩阵平面
[[1,2,3,4],[5,6,7,8]]
第1个矩阵平面
[[9,10,11,12],[13,14,15,16]]

z[0] 取第0个矩阵平面的元素
array([[ 0,  1,  2,  3],[ 4,  5,  6,  7]])
z[1] 取第1个矩阵平面的元素
array([[9,10,11,12],[13,14,15,16]])

z[:1] 取从0开始到1-1=0个矩阵平面的元素
如果[] 以冒号逗号 (即:,) 开头取矩阵平面的行元素
z[:,0]  取所有矩形平面的第0行
array[[1,2,3,4],[9,10,11,12]]
z[:,1]  取所有矩形平面的第1行
array[[5,6,7,8],[13,14,15,16]]

取指定某个矩阵平面的某一行 使用[矩阵平面号][行号]来表示
取指定某个矩阵平面的某一列 使用[矩阵平面号][:,列号]来表示
z[0][1] 取第0个矩阵平面的第一行
array([5,6,7,8])

z[1][0] 取第1个矩阵平面的第0行
array([9,10,11,12])

z[0][:,2] 取第0个矩阵平面的第2列
array([3,7])

z[1][:,3] 取第1个矩阵平面的第3列
array([12,16])

如果[]以两个冒号逗号(即:,:,)开头,表示取矩阵平面的列元素
z[:,:,0]  取所有矩阵平面的第0列
array([1,5],[9,13])

z[:,:,2]  取所有矩阵平面的第2列
array([3,7],[11,15])

取三维数组的某个具体元素,使用[矩阵平面号][行号][列号]的方式来表示
z[0][1][2]  取第0个矩阵平面第1行第2列的数据
7

z[1][1][1]  取第1个矩阵平面第1行第1列的数据
14

轴转换 arr.transpose((1, 0, 2))
交换数组

arr.swapaxes(1, 2) 是 NumPy 中用于交换数组指定两个轴的功能。以下是对其含义的详细解释：
swapaxes 的作用
swapaxes 方法会返回一个新的数组，其中指定的两个轴被交换。
原始数组的数据不会改变，只是轴的顺序发生了变化。
numpy.swapaxes(arr, axis1, axis2)
参数说明：
arr：输入的多维数组。
axis1：需要交换的第一个轴。
axis2：需要交换的第二个轴。
返回值：
返回一个视图（view），原始数据不发生改变。
创建三维数组
假设我们有一个形状为 (2, 3, 4) 的三维数组：
原始数组：
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
原始形状： (2, 3, 4)

(2) 使用 swapaxes(1, 2)
交换第 1 轴和第 2 轴：

交换后的数组：
[[[ 0  4  8]
  [ 1  5  9]
  [ 2  6 10]
  [ 3  7 11]]

 [[12 16 20]
  [13 17 21]
  [14 18 22]
  [15 19 23]]]
交换后的形状： (2, 4, 3)
3. 详细解释
(1) 原始数组的结构
原始数组的形状为 (2, 3, 4)，表示：
第 0 轴（深度）：有 2 个二维平面。
第 1 轴（行）：每个平面有 3 行。
第 2 轴（列）：每行有 4 列。
(2) 交换轴的效果
swapaxes(1, 2) 将第 1 轴（行）和第 2 轴（列）进行了交换：
原来的第 1 轴（行）变成了新的第 2 轴。
原来的第 2 轴（列）变成了新的第 1 轴。
第 0 轴（深度）保持不变。
因此，交换后的形状变为 (2, 4, 3)。
(3) 数据排列的变化
在原始数组中：
每个二维平面的形状为 (3, 4)，即 3 行 4 列。
交换后：
每个二维平面的形状变为 (4, 3)，即 4 行 3 列。
原始数组中，第一个二维平面为
  [[0, 1, 2, 3],
   [4, 5, 6, 7],
   [8, 9, 10, 11]]

交换后，第一个二维平面变为：
  [[0, 4, 8],
   [1, 5, 9],
   [2, 6, 10],
   [3, 7, 11]]

arr.swapaxes(1, 2)
将数组的第 1 轴和第 2 轴进行交换。
形状从 (2, 3, 4) 变为 (2, 4, 3)。
数据的排列方式也相应调整，但原始数据内容保持不变。
这种操作常用于调整多维数组的维度顺序，特别是在处理图像、张量或其他高维数据时非常有用。

以下是对 arr.transpose((1, 0, 2)) 的详细解释：
1. transpose 的作用
transpose 是 NumPy 中用于重新排列数组轴顺序的方法。
它返回一个视图（view），不会改变原始数组的数据，但会调整数据的访问顺序。
语法：
numpy.transpose(arr, axes=None)
arr：输入的多维数组。
axes：指定新的轴顺序。如果省略，则默认反转所有轴的顺序。
创建三维数组
假设我们有一个形状为 (2, 3, 4) 的三维数组：
import numpy as np

arr = np.arange(24).reshape((2, 3, 4))
原始数组：
[[[ 0  1  2  3]
  [ 4  5  6  7]
  [ 8  9 10 11]]

 [[12 13 14 15]
  [16 17 18 19]
  [20 21 22 23]]]
原始形状： (2, 3, 4)
(2) 使用 arr.transpose((1, 0, 2))
将轴的顺序调整为 (1, 0, 2)：

transposed_arr = arr.transpose((1, 0, 2))
交换后的数组：
[[[ 0  1  2  3]
  [12 13 14 15]]

 [[ 4  5  6  7]
  [16 17 18 19]]

 [[ 8  9 10 11]
  [20 21 22 23]]]
交换后的形状： (3, 2, 4)

3. 详细解释
(1) 原始数组的结构
原始数组的形状为 (2, 3, 4)，表示：
第 0 轴（深度）：有 2 个二维平面。
第 1 轴（行）：每个平面有 3 行。
第 2 轴（列）：每行有 4 列。
(2) 调整轴顺序的效果
arr.transpose((1, 0, 2)) 将轴的顺序调整为 (1, 0, 2)：
原来的第 1 轴（行）变成了新的第 0 轴。
原来的第 0 轴（深度）变成了新的第 1 轴。
原来的第 2 轴（列）保持不变，仍然是新的第 2 轴。
因此，调整后的形状变为 (3, 2, 4)。
(3) 数据排列的变化
在原始数组中：
每个二维平面的形状为 (3, 4)，即 3 行 4 列。
调整后：
每个二维平面的形状变为 (2, 4)，即 2 行 4 列。
平面的数量从 2 个变为 3 个。
例如：
原始数组中，第一个二维平面为：
  [[0, 1, 2, 3],
   [4, 5, 6, 7],
   [8, 9, 10, 11]]
原始数组中，第一个二维平面为：
  [[0, 1, 2, 3],
   [12, 13, 14, 15]]

总结
arr.transpose((1, 0, 2))
将数组的轴顺序调整为 (1, 0, 2)。
形状从 (2, 3, 4) 变为 (3, 2, 4)。
数据的排列方式也相应调整，但原始数据内容保持不变。
这种操作常用于调整多维数组的维度顺序，特别是在处理图像、张量或其他高维数据时非常有用。例如，在图像处理中，可能需要将颜色通道（如 RGB）从最后一个轴移动到第一个轴，以便进行特定的计算或显示操作。



通用函数 ufunc 是一种对ndarray中的数据执行元素级运算的函数 可以看做简单函数 接收一个或多个标量值,并产生一个或多个标量值的矢量化包装器

arr = np.arange(10)
np.arange 是 NumPy 中的一个函数，用于生成一个等差数列数组。
参数 10 表示生成从 0 到 9 的整数序列（共 10 个元素）。
结果是一个一维数组：[0, 1, 2, ..., 9]。

计算每个元素的平方根
np.sqrt(arr)
np.sqrt
np.sqrt 是 NumPy 中的一个函数，用于计算数组中每个元素的平方根。
输入是一个数组或标量，返回值是一个与输入形状相同的数组，其中每个元素是原数组对应元素的平方根。

计算每个元素的自然指数
np.exp(arr)
np.exp
np.exp 是 NumPy 中的一个函数，用于计算数组中每个元素的自然指数（以 e 为底的指数）。
公式为：exp(x) = e^x，其中 e ≈ 2.718 是自然对数的底数。
输入是一个数组或标量，返回值是一个与输入形状相同的数组，其中每个元素是原数组对应元素的自然指数。
exp(0)=1
exp(1) ≈ 2.718
exp(2) ≈ 7.389
这些操作都是逐元素进行的 即对数组中的每个元素独立计算,结果是一个与输入形状相同的数组

# add或maximum 接受2个数组因此也叫二元函数 并返回一个结果数组
x = np.random.randn(8)
np.random.randn
np.random.randn 是 NumPy 中的一个函数，用于生成符合标准正态分布（均值为 0，标准差为 1）的随机数。
参数 8 表示生成一个长度为 8 的一维数组，其中每个元素是从标准正态分布中随机抽取的浮点数。

y = np.random.randn(8)
np.maximum(x,y)
np.maximum
np.maximum 是 NumPy 中的一个通用函数（ufunc），用于对两个数组中的对应元素进行逐元素比较，并返回较大的值。
输入可以是标量或数组。如果输入是两个数组，则它们的形状必须相同（或满足广播规则）。
输出是一个与输入形状相同的数组，其中每个元素是两个输入数组对应位置元素的最大值。

总结
x = np.random.randn(8) 和 y = np.random.randn(8)
分别生成两个长度为 8 的一维数组，包含从标准正态分布中随机抽取的浮点数。
np.maximum(x, y)
对两个数组中的对应元素进行逐元素比较，返回较大的值。
输出是一个与输入形状相同的一维数组。
这种操作在数值计算中非常常见，特别是在需要对两个数据集进行逐元素比较并取最大值时。

arr = np.arange(10)

np.sqrt(arr)
np.exp(arr)

# add或maximum 接受2个数组因此也叫二元函数 并返回一个结果数组
x = np.random.randn(8)
y = np.random.randn(8)
np.maximum(x,y)


arr = np.random.randn(7) * 5
np.random.randn(7)
np.random.randn 是 NumPy 中的一个函数，用于生成符合标准正态分布（均值为 0，标准差为 1）的随机数。
参数 7 表示生成一个长度为 7 的一维数组，其中每个元素是从标准正态分布中随机抽取的浮点数。
* 5
将生成的随机数组中的每个元素乘以 5。这相当于对随机数进行缩放操作，使得生成的随机数范围扩大或缩小。



remainder,whole_part = np.modf(arr)
np.modf
np.modf 是 NumPy 中的一个通用函数（ufunc），用于将数组中的每个元素分解为小数部分和整数部分。
返回两个数组：
第一个数组是输入数组中每个元素的小数部分（remainder）。
第二个数组是输入数组中每个元素的整数部分（whole_part）。

解释
对于 arr 中的每个元素，np.modf 将其分解为小数部分和整数部分：
小数部分（remainder）始终保留符号（正负号）。
整数部分（whole_part）取最接近零的整数，并保留符号。
例如：
对于 -2.3456789：
小数部分：-0.3456789
整数部分：-2
对于 4.56789012：
小数部分：0.56789012
整数部分：4
对于 -0.98765432：
小数部分：-0.98765432
整数部分：-0

arr = np.random.randn(7) * 5
生成一个长度为 7 的一维数组，包含从标准正态分布中随机抽取并乘以 5 的浮点数。
remainder, whole_part = np.modf(arr)
将数组 arr 中的每个元素分解为小数部分（remainder）和整数部分（whole_part）。
小数部分保留符号，整数部分取最接近零的整数并保留符号。
这种操作在数值计算中非常常见，特别是在需要分离数字的小数部分和整数部分时。

-元ufunc
abs、fabs    计算整数、浮点数或复数的绝对值。对于非复数值，可以使用更快的fabs
sqrt    计算各元素的平方根。相当于arr*0.5
square  计算各元素的平方。相当于arr*2
exp 计算各元素的指数e×
log、log10、log2、log1p    分别为自然对数（底数为e)、底数为10的1og、底数为2的log、log(1+x)
sign    计算各元素的正负号：1（正数）、0（零）、一1（负数)
ceil    计算各元素的ceiling值，即大于等于该值的最小整数
floor   计算各元素的oor值，即小于等于该值的最大整数

rint    将各元素值四舍五入到最接近的整数，保留dtype
modf    将数组的小数和整数部分以两个独立数组的形式返回
isnan   返回一个表示“哪些值是NaN（这不是一个数字）”的布尔型数组
isfinite、isinf  分别返回一个表示“哪些元素是有穷的（非inf，非NaN）”或“哪些元素是无穷的”的布尔型数组cos、cosh、sin、sinh、
普通型和双曲型三角函数tan、tanh

arccos、arccosh、arcsin、  反三角函数
arcsinh、arctan、arctanh
logical_not 计算各元素notx的真值。相当于-arr

二元ufunc
add 将数组中对应的元素相加
subtract    从第一个数组中减去第二个数组中的元素
multiply    数组元素相乘
divide、floor divide 除法或向下圆整除法（丢弃余数）
power   对第一个数组中的元素A,根据第二个数组中的相应元素B,计算AB
maximum、fmax    元素级的最大值计算。fmax将忽略NaN
minimum、fmin    元素级的最小值计算。fmin将忽略NaN
mod 元素级的求模计算（除法的余数）》
copysign    将第二个数组中的值的符号复制给第一个数组中的值

greater、greater._equal、.执行元素级的比较运算，最终产生布尔型数组。相当于中缀运
less、less_equal、算符>、>=、<、<=、=、=
equal、not_equal
logical_and、logical_or、执行元素级的真值逻辑运算。相当于中缀运算符&、、A
logical_xor

"""
from array import array

import numpy as np

arr = np.random.randn(7) * 5
remainder,whole_part = np.modf(arr)
print(remainder)
print(whole_part)





if __name__ == '__main__':
    pass